﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using PSE.Framework.ProviderLoader;
using PSE.Framework.ProviderLoader.Configuration;
using PSE.Framework.Configuration;

namespace PSE.Framework.UI.Settings.Providers
{
    public class LocalConfigurationSettingsHandler : BaseProvider, IConfigurationSettingsHandler<ConfigurationObjectType>
    {

        private const string FILE_EXTENSION = "*.xml";

        private const string FILE_PATH = @"\{0}\Settings\";

        private const string LOCAL_SETTINGS_PROVIDER = "localSettingsProvider";


        public LocalConfigurationSettingsHandler(ProviderConfigurationElement configuration)
            : base(configuration)
        {
        }

        private string GetPath(ConfigurationObjectType configurationType)
        {
            ProductConfigurationSection configSection = ApplicationConfiguration.GetCurrent().GetSection<ProductConfigurationSection>("productConfiguration");
            string path = string.Format(@"{0}{1}", System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), string.Format(FILE_PATH, configSection.ProductName));
            path += configurationType.ToString() + @"\";
            return path;
        }

        private bool SaveSettings(IConfigurationObject<ConfigurationObjectType> configuration)
        {
            ProviderConfigurationSection configSection = ApplicationConfiguration.GetCurrent().GetSection<ProviderConfigurationSection>("clientProviders");

            IConfigurationSettings<ConfigurationObjectType> settings = ProviderLoader<IConfigurationSettings<ConfigurationObjectType>>.LoadProvider(configSection.Providers, LOCAL_SETTINGS_PROVIDER);

            return settings.Save(configuration);
        }

        public bool ChangePropertyValue<T>(IConfigurationObject<ConfigurationObjectType> configuration, string propertyName, object value)
            where T : IConfigurationObject<ConfigurationObjectType>
        {
            Type typeT = typeof(T);

            PropertyInfo prop = typeT.GetProperty(propertyName);

            if (prop != null)
            {
                prop.SetValue(configuration, value, null);
                return this.SaveSettings(configuration);
            }

            return false;
        }

        public void ChangeAllPropertiesValue<T>(ConfigurationObjectType configurationType, string propertyName, object value)
            where T : IConfigurationObject<ConfigurationObjectType>, new()
        {
            List<IConfigurationObject<ConfigurationObjectType>> listConfigObject = this.GetConfigurationObjects<T>(configurationType);

            if (listConfigObject != null)
            {
                foreach (IConfigurationObject<ConfigurationObjectType> config in listConfigObject)
                {
                    this.ChangePropertyValue<T>(config, propertyName, value);
                }
            }
        }


        public List<IConfigurationObject<ConfigurationObjectType>> GetConfigurationObjects<T>(ConfigurationObjectType configurationType)
            where T : IConfigurationObject<ConfigurationObjectType>, new()
        {
            List<IConfigurationObject<ConfigurationObjectType>> listConfigObject = new List<IConfigurationObject<ConfigurationObjectType>>();

            string path = this.GetPath(configurationType);

            if (System.IO.Directory.Exists(path))
            {
                string[] fileList = System.IO.Directory.GetFiles(path, FILE_EXTENSION);

                ProviderConfigurationSection configSection = ApplicationConfiguration.GetCurrent().GetSection<ProviderConfigurationSection>("clientProviders");

                IConfigurationSettings<ConfigurationObjectType> settings = ProviderLoader<IConfigurationSettings<ConfigurationObjectType>>.LoadProvider(configSection.Providers, LOCAL_SETTINGS_PROVIDER);

                foreach (string file in fileList)
                {
                    IConfigurationObject<ConfigurationObjectType> configObject = new T();
                    System.IO.FileInfo fileInfo = new System.IO.FileInfo(file);
                    configObject.ConfigurationName = fileInfo.Name.Replace(fileInfo.Extension, "");
                    configObject.ConfigurationType = configurationType;

                    if (settings.Load(ref configObject))
                    {
                        listConfigObject.Add(configObject);
                    }

                }

                settings = null;
            }

            if (listConfigObject.Count > 0)
                return listConfigObject;
            else
                return null;
        }
    }
}
